#ifndef __GWCOMMANDLINE_H__
#define __GWCOMMANDLINE_H__

#include <vector>
#include <string.h>
#include "../util/gwcommon.h"
#include "../util/gwconvertshell.hpp"
#include "../util/gwcastfunc.hpp"

/**
*@file       gwcommandline.h
*@brief      parse command line arguments( format like: -x 780 -y555 )
*
*@author     graywind
*@version    1.0.0.0
*@data       2011/12/27
*/

///application stuff
namespace gwBedrockApp
{
        ///parse command line
        class gwCommandLine;
}

///application stuff
namespace gwBedrockApp
{
        ///parse command line
        class gwCommandLine
        {
        public:
                ///@brief    define convertible string type
                typedef gwBedrockUtil::gwConvertShell<std::string, gwBedrockUtil::gwLexicalCast>    gwConvertString;
                ///@brief    define the arrary of convertible strings
                typedef std::vector<gwConvertString>                                                ArgumentArray;

        private:
                ///@brief    count of arguments
                int                        m_iArgNum;
                ///@brief    array of convertible strings
                ArgumentArray     m_ArgArray;


                ///@brief    find the option specificed by user
                ///param[in] option    name of option
                ///retval    int       the index of option in the array(return -1 if failed)
                int          FindIndex(const std::string& option);


        public:
                ///@brief    convert the standard command line arguments to a string object
                ///param[in] argc      from standard command line arguments
                ///param[in] argv    from standard command line arguments
                ///retval    std::string
                static std::string ConvertCmdArgToString(int argc, char** argv);


        public:
                ///@brief    default constructor
                gwCommandLine();
                ///@brief    construct from standard command line
                ///param[in] argc      from standard command line arguments
                ///param[in] argv    from standard command line arguments
                gwCommandLine(int argc, char** argv);
                ///@brief    construct from a string object
                ///param[in] cmdLine    string object through the ConvertCmdArgToString() function
                gwCommandLine(const std::string& cmdLine);
                ///@brief    copy constructor
                ///param[in] rhs another gwCommandLine object
                explicit gwCommandLine(const gwCommandLine& rhs);
                ///@brief    destructor
                ~gwCommandLine();


        public:
                ///@brief      get the file name
                ///retval      std::string
                std::string       GetFileName() const;
                ///@brief      get the option value and convert to bool
                ///param[in]   option         name of option
                ///param[in]   defaultValue   if failed return this value
                ///retval      bool
                bool              GetBool(const std::string& Option, bool defaultValue = false);
                ///@brief      get the option value and convert to int
                ///param[in]   option         name of option
                ///param[in]   defaultValue   if failed return this value
                ///retval      int
                int               GetInt(const std::string& Option, int  defaultValue = 0);
                ///@brief      get the option value and convert to float
                ///param[in]   option         name of option
                ///param[in]   defaultValue   if failed return this value
                ///retval      float
                float             GetFloat(const std::string& Option, float defaultValue = 0.0f);
                ///@brief      get the option value and convert to std::string
                ///param[in]   option         name of option
                ///param[in]   defaultValue   if failed return this value
                ///retval      std::string
                std::string       GetString(const std::string& Option, const std::string& defaultValue = "null");

                ///@brief      get the option value and convert to bool
                ///param[in]   index          index in the array
                ///param[in]   defaultValue   if failed return this value
                ///retval      bool
                bool              GetBoolByIndex(unsigned int index, bool defaultValue = false);
                ///@brief      get the option value and convert to int
                ///param[in]   index          index in the array
                ///param[in]   defaultValue   if failed return this value
                ///retval      int
                int               GetIntByIndex(unsigned int index, int  defaultValue = 0);
                ///@brief      get the option value and convert to float
                ///param[in]   index          index in the array
                ///param[in]   defaultValue   if failed return this value
                ///retval      float
                float             GetFloatByIndex(unsigned int index, float defaultValue = 0.0f);
                ///@brief      get the option value and convert to std::string
                ///param[in]   index          index in the array
                ///param[in]   defaultValue   if failed return this value
                ///retval      std::string
                std::string       GetStringByIndex(unsigned int index, const std::string& defaultValue = "null");



                ///@brief     get arguments number
                ///retval     int
                int GetArgumentNumber() const;
                ///@brief     get last error
                ///retval     const char*   error reason
                const char* GetLastError() const;

        public:
                ///@brief     override operator=
                ///retval     gwCommandLine&    reference object of this instance
                gwCommandLine&            operator=(const gwCommandLine& rhs);

        protected:
                ///@brief     last error string
                const  char*       m_pcLastErrror;

                ///@brief     this means can't find argument follow the option
                static char        m_strOpitionNotFound[];
                ///@brief     this error means there are not any options
                static char        m_strOptionRequire[];
        };

        /***************************************************************************************************************************/
        inline
        std::string
        gwCommandLine::GetFileName() const
        {
                if (m_ArgArray.size() > 0)
                {
                        return m_ArgArray[0].AsString();
                }
                return std::string("");
        }

        /***************************************************************************************************************************/
        inline
        int
        gwCommandLine::GetArgumentNumber() const
        {
                return m_iArgNum;
        }

        /***************************************************************************************************************************/
        inline
        const char*
        gwCommandLine::GetLastError() const
        {
                return m_pcLastErrror;
        }
}
#endif
